cc.Class({
    extends: cc.Component,

    properties: {
        nodes :  [cc.Node],
        baseNode:cc.Prefab,
        ship:cc.Node,

        isAngle:false,
        moveAngel:50,
        time:4,

        configList: {
            default: null,
            type: cc.JsonAsset,
        },
    },

    // use this for initialization
    onLoad: function () {
        this.roundLength = 0
        this.movedDelta = 0
        this.posList = []

        this.pathNodes = []

        var self = this
        cc.director.on("FlagNodeMoveEnd", function (argument) {
            console.log("~~FlagNodeMoveEnd")
            self.gen()
        });

        // this.gen()
    },

    run()
    {
        this.run = true
        // this.onMove(this.ship, false, 0, 5, this.posList, false)

        // var poses = [];
        // for(let i=0;i<this.nodes.length;i++)
        // {
        //     poses.push(this.nodes[i].getPosition());
        // }
        
        // this.ship.setPosition(poses[0])

        // var bezier1 = [poses[0], poses[1], poses[2]];
        // var bezierTo1 = cc.bezierTo(2, bezier1);

        // var bezier2 = [poses[2], poses[3], poses[4]];
        // var bezierTo2 = cc.bezierTo(2, bezier2);

        // var bezier3 = [poses[4], poses[5], poses[6]];
        // var bezierTo3 = cc.bezierTo(2, bezier3);

        // var bezier4 = [poses[6], poses[7], poses[0]];
        // var bezierTo4 = cc.bezierTo(2, bezier4);

        // var seq = cc.sequence(bezierTo1, bezierTo2, bezierTo3, bezierTo4);
        // this.ship.runAction(seq)
    },

    load()
    {
        this.nowAction = null;
        var self = this
        cc.loader.loadRes('path', function (err, asset) {
            self.posList = []
            asset.forEach(e => {
                self.posList.push(new cc.Vec2(e.PosX, e.PosY))
            });
            self.onMove(self.ship, false, 0, 5, self.posList, false)
        });
    },

    save()
    {
        if(this.posList <= 10)
            return
        console.log("~~on click add save");
        var writeablePath = jsb.fileUtils.getWritablePath();
        console.log("~~Path : " + writeablePath);
        var dataFilePath = writeablePath + "path.json";

        var itemDataList = [];
        for(var i in this.posList)
        {
            var item = this.posList[i];
            var itemData = {};
            itemData.PosX = item.x;
            itemData.PosY = item.y;
            itemDataList.push(itemData);
        }

        var jsonDataStr = JSON.stringify(itemDataList);
        console.log("~~jsonDataStr : " + jsonDataStr);
        jsb.fileUtils.writeStringToFile(jsonDataStr, dataFilePath);
    },

    gen()
    {
        this.pathNodes.forEach(element => {
            element.destroy()
        });

        var poses = [];
        this.posList = []
        this.pathNodes = []
        this.roundLength = 0
        for(let i=0;i<this.nodes.length;i++)
        {
            poses.push(this.nodes[i].getPosition());
        }
        
        var newPosList = this.createCurve(poses);

        for(let i=0;i<newPosList.length;i++)
        {
            if(i%10 === 0)
            {
                var newNode = cc.instantiate(this.baseNode);
                newNode.parent = this.node;
                newNode.setPosition(newPosList[i]);
                this.pathNodes.push(newNode)
            }
       
            this.posList.push(new cc.Vec2(newPosList[i].x, newPosList[i].y));

            var nextIndex = i+1;
            if(nextIndex === newPosList.length)
            {
                nextIndex = 0;
            }
            var nextPos = newPosList[nextIndex];
            this.roundLength = this.roundLength + nextPos.sub(newPosList[i]).mag();
        }
    },

    addSpeed()
    {
        // cc.speed
        this.onMove(this.ship, false, 0, 5, this.posList, true)
    },

    // called every frame
    update: function (dt) 
    {
        {
            obj = this.ship,
            idx = 0,
            speed = 500
        }

        if(this.run)
        {
            let speed = this.instance.speed;
            let sumDistance = dt*speed
            let currentIdx = this.instance.idx

            let nextIdx = currentIdx + 1
            if(nextIdx >= this.posList.length){
                nextIdx = 0
            }

            let nowPos = this.instance.obj.getPosition()
            do{
                let nextPos = this.posList[nextIdx]
                var distance = nextPos.sub(nowPos).mag()
                if(distance >= sumDistance){
                    let moveV2 = (nextPos - nowPos)*(sumDistance/distance)
                    let resultPos = nowPos + moveV2
                    let rotation = this.getRotation(nowPos, nextPos)
                    break
                }else{
                    sumDistance -= distance
                    nowPos = nextPos

                    nextIdx++
                    if(nextIdx >= this.posList.length){
                        nextIdx = 0
                    }
                }
            }while(sumDistance>0)
        }
        // var speed = 500;
        // this.movedDelta = this.movedDelta+dt*speed;
        // while(this.movedDelta >= this.roundLength)
        // {
        //     this.movedDelta -= this.roundLength;
        // }

        // var newDelta = this.movedDelta;
        // var nowIndex = 0;
        // do{
        //     var nowNode = this.posList[nowIndex];
        //     var nextIndex = nowIndex+1;

            
        //     if(nextIndex == this.posList.length)
        //     {
        //         nextIndex = 0;
        //     }
        //     var nextPos = this.posList[nextIndex];
        //     var rotation = this.getRotation(nowNode, nextPos)
        //     // console.log("!!", rotation)

        //     var length = nextPos.sub(nowNode).mag();
        //     if(newDelta > length)
        //     {
        //         newDelta-=length;
        //         nowIndex++;
        //     }else
        //     {
        //         var deltaPos = nextPos.sub(nowNode);
        //         var targetPos = deltaPos.mul(newDelta/length);
        //         targetPos = targetPos.add(nowNode);
        //         this.ship.setPosition(targetPos);
        //         this.ship.rotation = rotation
        //         break;
        //     }
        // }while(newDelta>0);
    },

    onMove(ship, isAngle, angleSpeed, roundTime, list, isAddSpeed)
    {
        console.log("onmove isAddSpeed", isAddSpeed)
        if(list.length <= 1)
            return

        let roundLength = 0
        for(let i=0;i<list.length;i++)
        {
            var nextIndex = i+1;
            if(nextIndex === list.length){
                nextIndex = 0;
            }
            var nextPos = list[nextIndex];
            roundLength = roundLength + nextPos.sub(list[i]).mag();
        }

        let action = this.genAction(list, isAngle, angleSpeed, roundLength/roundTime, isAddSpeed, this.ship)
        ship.stopAllActions()
        if(isAddSpeed)
            ship.runAction(cc.speed(cc.repeatForever(action), 2))
        else
            this.nowAction = ship.runAction(cc.repeatForever(action))
    },

    getCurrentIdx(ship, list)
    {
        for(let i=list.length-1; i>=0; i--)
        {
            let nowPt = list[i]
            let pt = ship.getPosition()
            let p = new cc.Vec2(pt.x, pt.y)
            if(nowPt.sub(p).mag() < 10)
            {
                if(i+3 > list.length)
                    return 0
                else
                    return i+3
            }
        }
        return 0
    },

    genAction(list, isAngle, angleSpeed, speed, isAddSpeed, ship)
    {
        if(list.length <= 1)
            return

        let begIdx = 0
        if(isAddSpeed)
            begIdx = this.getCurrentIdx(ship, list)

        let actionList = []
        for(let i=begIdx; i<list.length+begIdx; i++)
        {
            let idx = i
            if(idx >= list.length)
                idx = idx - list.length

            let nextIdx = idx+1
            if(nextIdx >= list.length)
                nextIdx = 0

            let nowPt = list[idx]
            let nextPt = list[nextIdx]

            let time = 1
            if(isAngle)
                time = this.getTime(nowPt, nextPt, angleSpeed)
            else
                time = this.getTime2(nowPt, nextPt, speed)

            let moveTo = cc.moveTo(time, nextPt);
            let angle = this.getRotation(nowPt, nextPt)
            let rotateTo = cc.rotateTo(time, angle);
            let action = cc.spawn(moveTo, rotateTo);
            actionList.push(action)
        }
        var seq = cc.sequence(actionList);
        return seq
    },

    getTime(pt1, pt2, angleSpeed)
    {
        let angle = pt1.angle(pt2)
        angle = 180 * angle / 3.14159
        let value = angleSpeed
        let time = angle / value
        console.log("``", angle, time)
        return time
    },

    getTime2(pt1, pt2, speed)
    {
        let length = pt1.sub(pt2).mag();
        return length/speed
    },

    getRotation:function(nowPt, nextPt){
        var v1 = cc.v2(nowPt.x, nowPt.y);
        var v2 = cc.v2(nextPt.x, nextPt.y);
        let v3 = v2.sub(v1)
        let v = cc.v2(1, 0);
        let num = v.signAngle(v3)
        num = num / 3.14159 * 180
        return num
    },
///////////////////////////////////////////////////////////////////////////////////
    bezier3funcX :function(uu,controlP){
        var part0 = controlP[0].x * uu * uu * uu;
        var part1 = 3 * controlP[1].x * uu * uu * (1 - uu);
        var part2 = 3 * controlP[2].x * uu * (1 - uu) * (1 - uu);
        var part3 = controlP[3].x * (1 - uu) * (1 - uu) * (1 - uu);
        return part0 + part1 + part2 + part3;
    },
     bezier3funcY :function(uu,controlP){
        var part0 = controlP[0].y * uu * uu * uu;
        var part1 = 3 * controlP[1].y * uu * uu * (1 - uu);
        var part2 = 3 * controlP[2].y * uu * (1 - uu) * (1 - uu);
        var part3 = controlP[3].y * (1 - uu) * (1 - uu) * (1 - uu);
        return part0 + part1 + part2 + part3;
    },

    createCurve :function(originPoint)
    {
        var curvePoint=[];
        var originCount=originPoint.length;
        var scale = 0.6;
        var midpoints=[];
        for(let i=0;i<originCount;i++)
        {
            midpoints.push(new cc.Vec2(0,0));
        }
        //生成中点
        console.log(originCount);
        for(var i = 0 ;i < originCount ; i++){
            var nexti = (i + 1) % originCount;
            midpoints[i].x = (originPoint[i].x + originPoint[nexti].x)/2.0;
            midpoints[i].y = (originPoint[i].y + originPoint[nexti].y)/2.0;
        }
        
        //平移中点
        var extrapoints=[];
        for(let i=0;i<2*originCount;i++)
        {
            extrapoints.push(new cc.Vec2(0,0));
        }
        for(var i = 0 ;i < originCount ; i++){
            var backi = (i + originCount - 1) % originCount;
            var midinmid=new cc.Vec2(0,0);
            midinmid.x = (midpoints[i].x + midpoints[backi].x)/2.0;
            midinmid.y = (midpoints[i].y + midpoints[backi].y)/2.0;
            var offsetx = originPoint[i].x - midinmid.x;
            var offsety = originPoint[i].y - midinmid.y;
            var extraindex = 2 * i;
            extrapoints[extraindex].x = midpoints[backi].x + offsetx;
            extrapoints[extraindex].y = midpoints[backi].y + offsety;
            //朝 originPoint[i]方向收缩
            var addx = (extrapoints[extraindex].x - originPoint[i].x) * scale;
            var addy = (extrapoints[extraindex].y - originPoint[i].y) * scale;
            extrapoints[extraindex].x = originPoint[i].x + addx;
            extrapoints[extraindex].y = originPoint[i].y + addy;
            
            var extranexti = (extraindex + 1)%(2 * originCount);
            extrapoints[extranexti].x = midpoints[i].x + offsetx;
            extrapoints[extranexti].y = midpoints[i].y + offsety;
            //朝 originPoint[i]方向收缩
            addx = (extrapoints[extranexti].x - originPoint[i].x) * scale;
            addy = (extrapoints[extranexti].y - originPoint[i].y) * scale;
            extrapoints[extranexti].x = originPoint[i].x + addx;
            extrapoints[extranexti].y = originPoint[i].y + addy;
            
        }
        
        var controlPoint=[];
        for(let i=0;i<4;i++)
        {
            controlPoint.push(new cc.Vec2(0,0));
        }
        //生成4控制点，产生贝塞尔曲线
       var lineCount=originCount;
        for(var i = 0 ;i < lineCount ; i++){
            controlPoint[0] = originPoint[i];
            var extraindex = 2 * i;
            controlPoint[1] = extrapoints[extraindex + 1];
            var extranexti = (extraindex + 2) % (2 * originCount);
            controlPoint[2] = extrapoints[extranexti];
            var nexti = (i + 1) % originCount;
            controlPoint[3] = originPoint[nexti];
            var u = 1;
            while(u >= 0){
                var px = this.bezier3funcX(u,controlPoint);
                var py = this.bezier3funcY(u,controlPoint);
                //u是步长
                u -= 0.005;
                var tempP =new cc.Vec2(px,py);
                curvePoint.push(tempP);
            }
        }
        return curvePoint;
    }
});
